#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>



int main()
{
    signal(SIGCHLD, SIG_IGN);
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        exit(1);
    }
    else if (id == 0)
    {
        // 子进程代码
        std::cout << "我是子进程,pid：" << getpid() << "，我正在运行！！" << std::endl;
        sleep(5);
        exit(1); // 子进程五秒后退出。
    }

    // 父进程代码
    while (1)
    {
        std::cout << "我是父进程，pid：" << getpid() << "，我正在做其他工作！！" << std::endl;
        sleep(1);
    }
    return 0;
}


// void handler(int signo)
// {
//     std::cout << "pid: "<<getpid()<<"; "<<signo << "号信号被捕捉！！" << std::endl;
//     //假设这个父进程有很多的子进程，有多个子进程同时退出，会给父进程发送多次14号信号
//     //但是信号只能保存一个，handler函数只能执行一次。
//     //所有这里需要循环式的等待，直至当前所有的子进程都被成功等待，才结束。
//     //waitpid，使用WNOHANG参数后，为非阻塞等待，
//     //等待成功返回被回收子进程的pid。
//     //等待失败（所有子进程都没成功回收）返回0；
//     //错误返回-1；
//     pid_t id;
//     while (id = waitpid(-1, nullptr,WNOHANG) > 0)
//     {
//         std::cout<<"等待成功！！"<<std::endl;
//     } 
//     //此时所有退出的子进程都被成功等待。
// }

// int main()
// {

//     signal(SIGCHLD, handler);
//     pid_t id = fork();
//     if (id < 0)
//     {
//         perror("fork");
//         exit(1);
//     }
//     else if (id == 0)
//     {
//         // 子进程代码
//         std::cout << "我是子进程,pid：" << getpid() << "，我正在运行！！" << std::endl;
//         sleep(5);
//         exit(1); // 子进程五秒后退出。
//     }

//     // 父进程代码
//     while (1)
//     {
//         std::cout << "我是父进程，pid：" << getpid() << "，我正在做其他工作！！" << std::endl;
//         sleep(1);
//     }
//     //父进程一直在做自己的事情，当子进程退出的时候，给父进程发送17）SIGCHLD信号，
//     //父进程发送软中断，去等待子进程。这样不需要阻塞等待和轮询等待了。

//     return 0;
// }

// volatile int flag = 0;
// void handler(int signo)
// {
//     std::cout<<signo<<"号信号被捕捉!!"<<std::endl;
//     std::cout<<"flag: 0 -> 1"<<std::endl;
//     flag = 1;
// }
// int main()
// {
//     signal(2,handler);
//     std::cout<<"进程正在运行,pid："<<getpid()<<std::endl;
//     while(!flag);
//     std::cout<<"进程正常退出！！"<<std::endl;
//     return 0;
// }

// void handler(int signo)
// {
//     int cnt =0;
//     std::cout<<"我捕捉到一个信号："<<signo<<std::endl;
//     while(1)
//     {
//         printf("cnt : %2d\r",cnt++);
//         fflush(stdout);
//         if(cnt == 20 )
//         {
//             break;
//         }
//         sleep(1);
//     }
// }

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_handler = handler;
//     act.sa_flags =0 ;
//     sigemptyset(&act.sa_mask);
//     //sa_mask,当我么正在处理某一个信号期间，此信号会自动被屏蔽。
//     //当我们处理某种信号的时候也顺便想屏蔽其他信号，就可以添加到sa_mask中。
//     //处理完成之后就会解除屏蔽。
//     sigaddset(&act.sa_mask, 3);
//     //处理2号信号的时候顺便屏蔽3号信号。
//     sigaction(2, &act, &oact);
//     while(1)
//     {
//         sleep(1);
//     }
//     return 0;
// }

// int main()
// {
//     signal(2, hendler);
//     sigset_t set, oset;
//     sigset_t pendingset;
//     sigemptyset(&set);
//     sigemptyset(&oset);
//     for(int i =0 ;i <= 31 ;i++)
//     {
//         sigaddset(&set,i);
//     }
//     sigprocmask(SIG_BLOCK, &set, &oset);
//     int cnt =0;
//     while (1)
//     {
//         sigemptyset(&pendingset);
//         sigpending(&pendingset);
//         std::cout << "runing!! pid: " << getpid() << std::endl;
//         for (int i = 31; i >= 1; i--)
//         {
//             if (sigismember(&pendingset, i))
//             {
//                 std::cout << '1';
//             }
//             else
//             {
//                 std::cout << '0';
//             }
//         }
//         std::cout<<std::endl;
//         sleep(1);
//         if(cnt == 5)
//         {
//             //恢复对信号的处理
//             sigprocmask(SIG_SETMASK, &oset, &set);
//             //解除屏蔽进程要切换到内核态。
//             //解除屏蔽的时候，会顺便递达一个信号。因为会从内核态返回用户态。
//         }
//         cnt++;
//     }

//     return 0;
// }

// int main()
// {
//     if((1<<(signo-1)) & PCB->block)
//     {
//         //信号阻塞，不抵达
//     }
//     else{
//         if((1<<(signo-1)) & PCB->pending)
//         {
//             //抵达该信号。
//         }
//     }

//     return 0;
// }

// void handler(int signo)
// {
//     std::cout<<"捕捉到一个信号："<<signo<<std::endl;
//     //不退出；
// }

// int main()
// {
//     //自定义所有信号的捕捉方法；
//     for(int i =1; i<=31; i++)
//     {
//         signal(i , handler);
//     }

//     while(1)
//     {
//         std::cout<<"进程运行中！！pid:"<<getpid()<<std::endl;
//         sleep(3);
//     }
//     return 0;
// }

// int main()
// {
//     //核心转储
//     int arr[10];
//     arr[10000] = 100;//数组越界
//     //C语言对于数组的越界是通过抽查的方式检查的。不一定能检查出来。
//     //数组越界不一定会导致程序崩溃，
//     return 0;
// }

// struct alarm
// {
//     uint64_t when;//未来的超时时间
//     int type;//闹钟的类型，一次性的还是周期性的
//     task_struct* p;//给那个进程设置闹钟。该进程的PCB
//     struct alarm* next;//链表结构
// }

// int main()
// {

//     return 0;
// }

// int cnt =0;

// void handler(int signo)
// {
//     std::cout<<"捕捉到一个信号："<<signo<<std::endl;
//     std::cout<<cnt<<std::endl;
//     //alarm(1);
//     exit(1);
// }

// int main(){

//     signal(SIGALRM, handler);
//     alarm(10);
//     sleep(3);
//     int ret = alarm(1);
//     std::cout<<ret<<std::endl;

//     while(1){
//         cnt++;
//     }
//     return 0;
// }

// void printsig(const sigset_t p)
// {
//     for( int i = 1; i<= 31; i++)
//     {
//         if(sigismember(&p,i)){
//             std::cout<<'1';
//         }
//         else{
//             std::cout<<'0';
//         }
//     }
//     std::cout<<std::endl;
// }

// int main()
// {
//     sigset_t s1,s2,p;
//     sigemptyset(&s1);
//     sigemptyset(&s2);
//     sigaddset(&s1, 2);
//     sigprocmask(SIG_BLOCK, &s1,&s2);
//     while(1)
//     {
//         sigemptyset(&p);
//         sigpending(&p);
//         printsig(p);
//         sleep(1);
//     }
//     return 0;
// }

// #include <signal.h>
// int sigemptyset(sigset_t *set);//清空
// int sigfillset(sigset_t *set);//置位
// int sigaddset (sigset_t *set, int signo);//添加signo信号
// int sigdelset(sigset_t *set, int signo);//删除signo信号
// int sigismember（const sigset_t *set, int signo);//判断是否包含signo信号

// //这个程序的作用是1秒钟之内不停地数数,1秒钟到了就被SIGALRM信号终止。
// int cnt = 0;
// void handler(int signo)
// {
//     std::cout<<"捕捉到一条信号："<<signo<<std::endl;
//     std::cout<<cnt<<std::endl;
//     alarm(1);//捕捉之后我们再给进程设置一个闹钟。
//     //exit(1);
// }

// //此进程就是每秒打印cnt的值
// int main()
// {
//     alarm(1);//设置一个时间为1秒的闹钟。
//     //一秒后给自己进程发送 14) SIGALRM
//     signal(14, handler);

//     while(true)
//     {
//         cnt++;
//         //std::cout<<cnt<<std::endl;
//     }
//     return 0;
// }

// void handler(int sig)
// {
//     printf("catch a sig : %d\n", sig);
// }
// int main()
// {
//     signal(SIGSEGV, handler);
//     sleep(1);
//     int *p = NULL;
//     *p = 100;
//     while (1)
//         ;
//     return 0;
// }

// void catchsig(int signo)
// {
//     std::cout<<"我捕捉到一个信号："<<signo<<std::endl;
//     sleep(1);
// }
// int main()
// {
//     signal(SIGFPE, catchsig);
//     while(true)
//     {
//         std::cout<<"我是一个进程，我正在运行——————————"<<std::endl;
//         sleep(1);
//         int i =10;
//         i = i/0;
//     }
//     return 0;
// }

// int main()
// {
//     int cnt =0;
//     while(true)
//     {

//         printf("cnt: %d\r", cnt);
//         fflush(stdout);
//         cnt++;

//         if(cnt == 10)
//         {
//             abort();
//         }
//         sleep(1);
//     }

//     return 0;
// }

// int main()
// {
//     int cnt =0;
//     while(true)
//     {

//         printf("cnt: %d\r", cnt);
//         fflush(stdout);
//         cnt++;

//         if(cnt == 10)
//         {
//             int ret = raise(3);
//             if(ret == -1)
//             {
//                 perror("raise");
//                 exit(1);
//             }
//         }

//         sleep(1);
//     }

//     return 0;
// }

// void handler(int signo)
// {
//     std::cout<<"我捕捉到2号信号，并且自定义了处理方法"<<std::endl;
// }

// int main()
// {
//     //这里是signal函数的调用，不是handler函数的调用
//     //这里只是设置了对2号进程的的捕捉方法，并不代表这此方法被调用了
//     //这个handler函数在收到对应的信号才能执行。
//     signal(2 , handler);

//      while(1){
//         std::cout<<"我是一个进程，我正在执行！！我的pid："<<getpid()<<std::endl;

//         sleep(1);
//      }
// }